Resolve file descriptors once per syscall - #1302
Conversation
Chunked syscalls re-resolved the caller's raw fd for every chunk, so a concurrent close plus open could make a later chunk operate on a different open file description that had reused the raw slot. Resolve the raw fd once into an `AnyTypedFd` that retains the subsystem's `Arc<TypedFd<_>>`, and thread that through the whole syscall. A racing close now makes later chunks fail with `EBADF` instead of silently following the reused slot. This covers `read`/`write`, the `iovec` variants, the large-buffer `read` chunking, `sendfile`, `mmap`, all socket syscalls, `fstat`/`faccessat`, and `dup`. The fd layer is consolidated to support that: - `AnyTypedFd::dispatch` replaces `FilesState::run_on_typed_fd`, with `as_fs`/`fs_only` and the `on_any_fd!` macro covering the cases that previously needed blocks of repeated no-op closures. - fd narrowing happens once, in `Task::typed_fd`/`FilesState::typed_fd`; `FsPath` stores `i32` so callers stop round-tripping through `u32`. - `sys_recvmmsg` and `sys_sendfile` take a single `files` borrow. - `AnyTypedFd` carries `Debug`/`subsystem_name` for diagnostics. Adds regression tests covering fd reuse under `readv`, `dup`, and socket lookups.
|
🤖 SemverChecks 🤖 No breaking API changes detected Note: this does not mean API is unchanged, or even that there are no breaking changes; simply, none of the detections triggered. |
Static review findings (5-min budget, dual-model review: GPT-5.6 Sol + Opus 5)Reviewed the actual diff vs 🟡 Medium —
|
Resolve raw file descriptors once and retain the resulting
AnyTypedFdthroughout each syscall. This prevents chunked operations from switching to a different open-file description when another task concurrently closes and reuses the raw descriptor.This updates file, memory-mapping, and socket syscalls, and consolidates typed-fd dispatch and narrowing.
Fixes #1261.